package values

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"reflect"
	"strings"
	"sync"
	"time"
	"unsafe"
)

// ToSliceAs 转换目标为任意类型的 []TypeBase 和 [][]TypeBase 切片, 如果转换失败, 则返回空的 []T 切片
//   - 通过断言快速处理基本的[]TypeBase 和 [][]TypeBase切片, 其他类型切片尝试反射检查后处理
//   - TypeBase: string | bool |	int | int8 | int16 | int32 | int64 |	uint | uint8 | uint16 | uint32 | uint64 |	float32 | float64 |	time.Time | time.Duration | time.Month | time.Weekday
func ToSliceAs[T TypeBase | TypeBaseSlice](v any) []T {
	val, _ := ToSliceAsE[T](v)
	return val
}

// ToSliceAsD 转换目标为任意类型的 []TypeBase 和 [][]TypeBase 切片, 如果转换失败, 则返回defaultVal指定的默认值
//   - 通过断言快速处理基本的[]TypeBase 和 [][]TypeBase切片, 其他类型切片尝试反射检查后处理
//   - TypeBase: string | bool |	int | int8 | int16 | int32 | int64 |	uint | uint8 | uint16 | uint32 | uint64 |	float32 | float64 |	time.Time | time.Duration | time.Month | time.Weekday
func ToSliceAsD[T TypeBase | TypeBaseSlice](v any, defaultVal []T) []T {
	if v == nil {
		return defaultVal
	}
	if val, err := ToSliceAsE[T](v); err == nil {
		return val
	}
	return defaultVal
}

// ToSliceAsE 转换目标为任意类型的 []TypeBase 和 [][]TypeBase 切片, 如果转换失败, 则返回空的 []T 切片和错误信息
//   - 通过断言快速处理基本的[]TypeBase 和 [][]TypeBase切片, 其他类型切片尝试反射检查后处理
//   - TypeBase: string | bool |	int | int8 | int16 | int32 | int64 |	uint | uint8 | uint16 | uint32 | uint64 |	float32 | float64 |	time.Time | time.Duration | time.Month | time.Weekday
func ToSliceAsE[T TypeBase | TypeBaseSlice](v any) ([]T, error) {
	return _toSliceAsE[T](UnderefVal(v))
}

// _toSliceAsE 转换目标为任意类型的 []TypeBase 和 [][]TypeBase 切片, 如果转换失败, 则返回空的 []T 切片和错误信息
//   - 待转换目标为已经UnderefVal处理的参数
func _toSliceAsE[T TypeBase | TypeBaseSlice](v any) ([]T, error) {
	toVal := []T{}
	if v == nil {
		return toVal, errors.New("ToSliceAsE: nil pointer not support")
	}
	switch vs := v.(type) {
	case []T:
		if len(vs) == 0 {
			return toVal, nil
		}
		return append(toVal, vs...), nil
	case []*T:
		if len(vs) == 0 {
			return toVal, nil
		}
		for _, item := range vs {
			if item == nil {
				continue
			}
			toVal = append(toVal, *item)
		}
		return toVal, nil
	case []byte:
		if json.Valid(vs) {
			vsAny := []any{}
			if err := json.Unmarshal(vs, &vsAny); err == nil {
				return _toSliceAsE[T](vsAny)
			} else {
				return toVal, fmt.Errorf("ToSliceAsE: []byte to []T type, failed unmarshal: %s", err.Error())
			}
		}
		// Like []uint8  After _toSliceAsBaseV to []T
	case string:
		if vs != "" && strings.HasPrefix(vs, "[") && strings.HasSuffix(vs, "]") && json.Valid([]byte(vs)) {
			vsAny := []any{}
			if err := json.Unmarshal([]byte(vs), &vsAny); err == nil {
				return _toSliceAsE[T](vsAny)
			} else {
				return toVal, fmt.Errorf("ToSliceAsE: string to []T type, failed unmarshal: %s", err.Error())
			}
		}
		return toVal, errors.New("ToSliceAsE: string to []T type not support")
	case bool,
		int, int8, int16, int32, int64,
		uint, uint8, uint16, uint32, uint64, uintptr,
		float32, float64,
		complex64, complex128,
		time.Time, time.Duration, time.Location, time.Month, time.Weekday, time.Ticker, time.Timer,
		struct{}, chan any, func(), unsafe.Pointer,
		bytes.Buffer, strings.Builder,
		reflect.Type, reflect.Value, reflect.Kind,
		sync.Mutex, sync.RWMutex, sync.Cond, sync.Once, sync.Pool, sync.WaitGroup, sync.Locker,
		error,
		json.Number:
		// 如果待转换值是Golang 常用的基本类型, 则直接返回错误信息
		return toVal, errors.New("ToSliceAsE: basicType to []T type not support")
	}
	// 通过断言判断待转换值是否为 []any / []TypeBase 类型
	if toVal, err, next := _toSliceAsBaseV[T](v); !next {
		return toVal, err
	}
	// 通过断言判断待转换值是否为[][]TypeBase 类型
	if toVal, err, next := _toSliceAsBaseVS[T](v); !next {
		return toVal, err
	}

	// 尝试反射检查是否为Slice或Array类型
	// 获取输入值的反射类型和值
	vType := reflect.TypeOf(v)
	vValue := reflect.ValueOf(v)
	if vType.Kind() == reflect.Ptr {
		if vValue.IsNil() {
			return toVal, errors.New("ToSliceAsE: input is a nil pointer")
		}
		vType = vType.Elem()
		vValue = vValue.Elem()
	}
	// 检查是否为切片或数组类型
	if vType.Kind() != reflect.Slice && vType.Kind() != reflect.Array {
		return toVal, fmt.Errorf("ToSliceAsE: unsupported type %T, expected slice or array", v)
	}
	// 如果长度为0，直接返回空切片
	if vValue.Len() == 0 {
		return toVal, nil
	}
	// 将Slice或Array转换为[]any类型
	vsAny := make([]any, 0, vValue.Len())
	for i := range vValue.Len() {
		vsAny = append(vsAny, vValue.Index(i).Interface())
	}
	// 先尝试断言转换, 将[]any解码为[]T类型
	isAssertion := true
	for i := range vsAny {
		if v, ok := vsAny[i].(T); ok {
			toVal = append(toVal, v)
		} else {
			isAssertion = false
			break
		}
	}
	if isAssertion {
		return toVal, nil
	}

	// 再尝试 json Unmarshal 解码转换, 将[]any解码为[]T类型
	toVal = make([]T, 0, vValue.Len())
	if data, err := json.Marshal(vsAny); err == nil {
		if err := json.Unmarshal(data, &toVal); err == nil {
			return toVal, nil
		}
	}
	return []T{}, fmt.Errorf("ToSliceAsE: type %T to type %T not support", v, toVal)
}

// 先通过断言判断待转换值是否为[]TypeBase 类型
func _toSliceAsBaseV[T TypeBase | TypeBaseSlice](v any) ([]T, error, bool) {
	toVal := []T{}
	// 先通过断言判断待转换值是否为[]TypeBase 类型
	switch vs := v.(type) {
	case []any:
		var toSubVal T
		switch any(toSubVal).(type) {
		case string, bool,
			int, int8, int16, int32, int64,
			uint, uint8, uint16, uint32, uint64, uintptr,
			float32, float64,
			time.Time, time.Duration, time.Location, time.Month, time.Weekday:
			// []TypeBase
			return _toSliceAsParseV[T](vs)
			// []TypeBaseSlice == [][]TypeBase
		case []string:
			return _toSliceAsParseSubVS[T, string](vs)
		case []bool:
			return _toSliceAsParseSubVS[T, bool](vs)
		case []int:
			return _toSliceAsParseSubVS[T, int](vs)
		case []int8:
			return _toSliceAsParseSubVS[T, int8](vs)
		case []int16:
			return _toSliceAsParseSubVS[T, int16](vs)
		case []int32:
			return _toSliceAsParseSubVS[T, int32](vs)
		case []int64:
			return _toSliceAsParseSubVS[T, int64](vs)
		case []uint:
			return _toSliceAsParseSubVS[T, uint](vs)
		case []uint8:
			return _toSliceAsParseSubVS[T, uint8](vs)
		case []uint16:
			return _toSliceAsParseSubVS[T, uint16](vs)
		case []uint32:
			return _toSliceAsParseSubVS[T, uint32](vs)
		case []uint64:
			return _toSliceAsParseSubVS[T, uint64](vs)
		case []float32:
			return _toSliceAsParseSubVS[T, float32](vs)
		case []float64:
			return _toSliceAsParseSubVS[T, float64](vs)
		case []time.Time:
			return _toSliceAsParseSubVS[T, time.Time](vs)
		case []time.Duration:
			return _toSliceAsParseSubVS[T, time.Duration](vs)
		case []time.Month:
			return _toSliceAsParseSubVS[T, time.Month](vs)
		case []time.Weekday:
			return _toSliceAsParseSubVS[T, time.Weekday](vs)
		}
		return toVal, nil, true
	case []string:
		return _toSliceAsParseV[T](vs)
	case []bool:
		return _toSliceAsParseV[T](vs)
	case []int:
		return _toSliceAsParseV[T](vs)
	case []int8:
		return _toSliceAsParseV[T](vs)
	case []int16:
		return _toSliceAsParseV[T](vs)
	case []int32:
		return _toSliceAsParseV[T](vs)
	case []int64:
		return _toSliceAsParseV[T](vs)
	case []uint:
		return _toSliceAsParseV[T](vs)
	case []uint8:
		return _toSliceAsParseV[T](vs)
	case []uint16:
		return _toSliceAsParseV[T](vs)
	case []uint32:
		return _toSliceAsParseV[T](vs)
	case []uint64:
		return _toSliceAsParseV[T](vs)
	case []float32:
		return _toSliceAsParseV[T](vs)
	case []float64:
		return _toSliceAsParseV[T](vs)
	case []time.Time:
		return _toSliceAsParseV[T](vs)
	case []time.Duration:
		return _toSliceAsParseV[T](vs)
	case []time.Month:
		return _toSliceAsParseV[T](vs)
	case []time.Weekday:
		return _toSliceAsParseV[T](vs)
	case []json.Number:
		return _toSliceAsParseV[T](vs)
	case []error:
		return _toSliceAsParseV[T](vs)
	case []*any:
		return _toSliceAsParseV[T](vs)
	case []*string:
		return _toSliceAsParseV[T](vs)
	case []*bool:
		return _toSliceAsParseV[T](vs)
	case []*int:
		return _toSliceAsParseV[T](vs)
	case []*int8:
		return _toSliceAsParseV[T](vs)
	case []*int16:
		return _toSliceAsParseV[T](vs)
	case []*int32:
		return _toSliceAsParseV[T](vs)
	case []*int64:
		return _toSliceAsParseV[T](vs)
	case []*uint:
		return _toSliceAsParseV[T](vs)
	case []*uint8:
		return _toSliceAsParseV[T](vs)
	case []*uint16:
		return _toSliceAsParseV[T](vs)
	case []*uint32:
		return _toSliceAsParseV[T](vs)
	case []*uint64:
		return _toSliceAsParseV[T](vs)
	case []*float32:
		return _toSliceAsParseV[T](vs)
	case []*float64:
		return _toSliceAsParseV[T](vs)
	case []*time.Time:
		return _toSliceAsParseV[T](vs)
	case []*time.Duration:
		return _toSliceAsParseV[T](vs)
	case []*time.Month:
		return _toSliceAsParseV[T](vs)
	case []*time.Weekday:
		return _toSliceAsParseV[T](vs)
	case []*json.Number:
		return _toSliceAsParseV[T](vs)
	case []*error:
		return _toSliceAsParseV[T](vs)
	}
	return toVal, nil, true
}

// 先通过断言判断待转换值是否为[][]TypeBase 类型
func _toSliceAsBaseVS[T TypeBase | TypeBaseSlice](v any) ([]T, error, bool) {
	var tVar T
	switch any(tVar).(type) {
	default:
		return []T{}, nil, true
	case []string:
		return _toSliceAsBaseLoopVS[T, string](v)
	case []bool:
		return _toSliceAsBaseLoopVS[T, bool](v)
	case []int:
		return _toSliceAsBaseLoopVS[T, int](v)
	case []int8:
		return _toSliceAsBaseLoopVS[T, int8](v)
	case []int16:
		return _toSliceAsBaseLoopVS[T, int16](v)
	case []int32:
		return _toSliceAsBaseLoopVS[T, int32](v)
	case []int64:
		return _toSliceAsBaseLoopVS[T, int64](v)
	case []uint:
		return _toSliceAsBaseLoopVS[T, uint](v)
	case []uint8:
		return _toSliceAsBaseLoopVS[T, uint8](v)
	case []uint16:
		return _toSliceAsBaseLoopVS[T, uint16](v)
	case []uint32:
		return _toSliceAsBaseLoopVS[T, uint32](v)
	case []uint64:
		return _toSliceAsBaseLoopVS[T, uint64](v)
	case []float32:
		return _toSliceAsBaseLoopVS[T, float32](v)
	case []float64:
		return _toSliceAsBaseLoopVS[T, float64](v)
	case []time.Time:
		return _toSliceAsBaseLoopVS[T, time.Time](v)
	case []time.Duration:
		return _toSliceAsBaseLoopVS[T, time.Duration](v)
	case []time.Month:
		return _toSliceAsBaseLoopVS[T, time.Month](v)
	case []time.Weekday:
		return _toSliceAsBaseLoopVS[T, time.Weekday](v)
	}
}
func _toSliceAsBaseLoopVS[T TypeBase | TypeBaseSlice, TV TypeBase](v any) ([]T, error, bool) {
	switch vs := v.(type) {
	default:
		return []T{}, nil, true
	case [][]any:
		return _toSliceAsParseVS[T, TV](vs)
	case *[][]any:
		return _toSliceAsParseVS[T, TV](*vs)
	case [][]*any:
		return _toSliceAsParseVS[T, TV](vs)
	case [][]string:
		return _toSliceAsParseVS[T, TV](vs)
	case *[][]string:
		return _toSliceAsParseVS[T, TV](*vs)
	case [][]*string:
		return _toSliceAsParseVS[T, TV](vs)
	case [][]bool:
		return _toSliceAsParseVS[T, TV](vs)
	case *[][]bool:
		return _toSliceAsParseVS[T, TV](*vs)
	case [][]*bool:
		return _toSliceAsParseVS[T, TV](vs)
	case [][]int:
		return _toSliceAsParseVS[T, TV](vs)
	case *[][]int:
		return _toSliceAsParseVS[T, TV](*vs)
	case [][]*int:
		return _toSliceAsParseVS[T, TV](vs)
	case [][]int8:
		return _toSliceAsParseVS[T, TV](vs)
	case *[][]int8:
		return _toSliceAsParseVS[T, TV](*vs)
	case [][]*int8:
		return _toSliceAsParseVS[T, TV](vs)
	case [][]int16:
		return _toSliceAsParseVS[T, TV](vs)
	case *[][]int16:
		return _toSliceAsParseVS[T, TV](*vs)
	case [][]*int16:
		return _toSliceAsParseVS[T, TV](vs)
	case [][]int32:
		return _toSliceAsParseVS[T, TV](vs)
	case *[][]int32:
		return _toSliceAsParseVS[T, TV](*vs)
	case [][]*int32:
		return _toSliceAsParseVS[T, TV](vs)
	case [][]int64:
		return _toSliceAsParseVS[T, TV](vs)
	case *[][]int64:
		return _toSliceAsParseVS[T, TV](*vs)
	case [][]*int64:
		return _toSliceAsParseVS[T, TV](vs)
	case [][]uint:
		return _toSliceAsParseVS[T, TV](vs)
	case *[][]uint:
		return _toSliceAsParseVS[T, TV](*vs)
	case [][]*uint:
		return _toSliceAsParseVS[T, TV](vs)
	case [][]uint8:
		return _toSliceAsParseVS[T, TV](vs)
	case *[][]uint8:
		return _toSliceAsParseVS[T, TV](*vs)
	case [][]*uint8:
		return _toSliceAsParseVS[T, TV](vs)
	case [][]uint16:
		return _toSliceAsParseVS[T, TV](vs)
	case *[][]uint16:
		return _toSliceAsParseVS[T, TV](*vs)
	case [][]*uint16:
		return _toSliceAsParseVS[T, TV](vs)
	case [][]uint32:
		return _toSliceAsParseVS[T, TV](vs)
	case *[][]uint32:
		return _toSliceAsParseVS[T, TV](*vs)
	case [][]*uint32:
		return _toSliceAsParseVS[T, TV](vs)
	case [][]uint64:
		return _toSliceAsParseVS[T, TV](vs)
	case *[][]uint64:
		return _toSliceAsParseVS[T, TV](*vs)
	case [][]*uint64:
		return _toSliceAsParseVS[T, TV](vs)
	case [][]float32:
		return _toSliceAsParseVS[T, TV](vs)
	case *[][]float32:
		return _toSliceAsParseVS[T, TV](*vs)
	case [][]*float32:
		return _toSliceAsParseVS[T, TV](vs)
	case [][]float64:
		return _toSliceAsParseVS[T, TV](vs)
	case *[][]float64:
		return _toSliceAsParseVS[T, TV](*vs)
	case [][]*float64:
		return _toSliceAsParseVS[T, TV](vs)
	case [][]time.Time:
		return _toSliceAsParseVS[T, TV](vs)
	case *[][]time.Time:
		return _toSliceAsParseVS[T, TV](*vs)
	case [][]*time.Time:
		return _toSliceAsParseVS[T, TV](vs)
	case [][]time.Duration:
		return _toSliceAsParseVS[T, TV](vs)
	case *[][]time.Duration:
		return _toSliceAsParseVS[T, TV](*vs)
	case [][]*time.Duration:
		return _toSliceAsParseVS[T, TV](vs)
	case *[][]time.Month:
		return _toSliceAsParseVS[T, TV](*vs)
	case [][]*time.Month:
		return _toSliceAsParseVS[T, TV](vs)
	case *[][]time.Weekday:
		return _toSliceAsParseVS[T, TV](*vs)
	case [][]*time.Weekday:
		return _toSliceAsParseVS[T, TV](vs)

	}
}
func _toSliceAsParseV[T TypeBase | TypeBaseSlice, V any](vs []V) ([]T, error, bool) {
	if vs == nil {
		return []T{}, errors.New("ToSliceAsE: nil pointer not support"), false
	}
	if len(vs) == 0 {
		return []T{}, nil, false
	}
	toVal := make([]T, 0, len(vs))
	for _, item := range vs {
		if val, ok := any(item).(T); ok {
			toVal = append(toVal, val)
			continue
		}
		if val, err := _toBaseE[T](UnderefVal(item)); err == nil {
			toVal = append(toVal, val)
		} else {
			return []T{}, fmt.Errorf("ToSliceAsE: %T to type %T, error: %s", item, val, err.Error()), false
		}
	}
	return toVal, nil, false
}
func _toSliceAsParseVS[T TypeBase | TypeBaseSlice, TV TypeBase, VV any](vs [][]VV) ([]T, error, bool) {
	if vs == nil {
		return []T{}, errors.New("ToSliceAsE: nil pointer not support"), false //
	}
	if len(vs) == 0 {
		return []T{}, nil, false
	}
	toVal := make([]T, 0, len(vs))
	for _, list := range vs {
		if len(list) == 0 {
			toVal = append(toVal, any([]TV{}).(T))
			continue
		}
		if val, ok := any(list).(T); ok {
			toVal = append(toVal, val)
			continue
		}
		if val, err := ToSliceAsE[TV](list); err == nil {
			toVal = append(toVal, any(val).(T))
			continue
		} else {
			return []T{}, fmt.Errorf("ToSliceAsE error: %s", err.Error()), false
		}
	}
	return toVal, nil, false
}
func _toSliceAsParseSubVS[T TypeBaseSlice | TypeBase, ST TypeBase](vs []any) ([]T, error, bool) {
	if vs == nil {
		return []T{}, errors.New("ToSliceAsE: nil pointer not support"), false
	}
	if len(vs) == 0 {
		return []T{}, nil, false
	}
	toVal := make([]T, 0, len(vs))
	for _, item := range vs {
		if val, err := ToSliceAsE[ST](item); err == nil {
			if v, ok := any(val).(T); ok {
				toVal = append(toVal, v)
			} else {
				return []T{}, fmt.Errorf("ToSliceAsE: []%T to type []%T", item, val), false
			}
		} else {
			return []T{}, fmt.Errorf("ToSliceAsE: %T to type %T, error: %s", item, val, err.Error()), false
		}
	}
	return toVal, nil, false
}
